import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';

const WxPay = require('wechatpay-node-v3')
import * as url from 'url'
import { Timeout } from '@nestjs/schedule';
import { DbService } from '../db/db.service';
import { CachingService } from '../caching/caching.service';
import { ConfigureService } from '@app/configure';

@Injectable()
export class WechatService {
    private wechatConfig:any;
    private flag = false;
    constructor(
        private readonly http:HttpService,
        private readonly db:DbService,
        private readonly cache:CachingService,
        private readonly configure:ConfigureService
        
    ){

    }

    //初始化配置
    @Timeout(0)
    initConfig() {
        this.config()
    }

    async config() {
        if(this.flag == false) {
            this.flag = true
            const conf = await this.db.platformConfig.queryConfig(['wechat'])
            if(conf && conf.wechat) {
                this.wechatConfig = conf.wechat
            }
        }

        return this.wechatConfig
    }

    async login(code:string) {
        const conf:any = this.config()
        if(!conf) return null

        const res = await this.http.axiosRef.get('https://api.weixin.qq.com/sns/jscode2session', {
            params : {
                appid : conf.appid,
                secret : conf.secret,
                grant_type : 'authorization_code',
                js_code : code
            }
        })

        return res.statusText == 'OK' ? res.data : null
    }


    //回调解密
    async decipher_gcm(ciphertext, associated_data, nonce) {
        const conf:any = this.config()
        if(!conf) return false
        const pay = new WxPay({
            appid: conf.appid,
            mchid: conf.mchid,
            publicKey: Buffer.from(conf.publicKey, 'utf-8'), // 公钥
            privateKey: Buffer.from(conf.privateKey, 'utf-8'), // 秘钥
        });

        return pay.decipher_gcm(ciphertext, associated_data, nonce, conf.v3Key);
    }


    //查询免密支付是否已经授权
    async queryPayscorePermissions(openid:string) {
        try {
            const conf:any = this.config()
            if(!conf) return null
            const res = await this.http.axiosRef.get('https://api.mch.weixin.qq.com/v3/payscore/permissions/openid/' + openid, {
                params : {
                    service_id : conf.serviceId,
                    appid : conf.appid
                }
            })

            if(res.statusText == 'OK') {
                return res.data.authorization_state == 'AVAILABLE'
            }

            return res.statusText == 'OK' ? res.data : null

        } catch (error) {
            console.log(error.message)
        }
        
        return null
    }

    //商户预授权
    async payscorePermissions(authorizationCode:string, userId:number) {
        try {
            const conf:any = this.config()
            if(!conf) return null
            
            let baseNotifyUrl = conf.notifyUrl
            if(baseNotifyUrl.endsWith('/') == false) {
                baseNotifyUrl += '/'
            }

            const res = await this.http.axiosRef.post('https://api.mch.weixin.qq.com/v3/payscore/permissions/openid', {
                service_id: conf.serviceId,
                appid: conf.appid,
                authorization_code: authorizationCode,
                notify_url: url.resolve(baseNotifyUrl, 'user/payscore/permissions/wx/' + userId)
            })

            if(res.statusText == 'OK') {
                return res.data.authorization_state == 'AVAILABLE'
            }

            return res.statusText == 'OK' ? res.data : null

        } catch (error) {
            console.log(error.message)
        }
        
        return null
    }

    //免密支付下单
    async payscoreServiceorder(out_order_no:string, openid:string, amount:number, startTime:string, service_introduction:string, notify_url:string) {
        try {
            const conf:any = this.config()
            if(!conf) return null
            const res = await this.http.axiosRef.post('https://api.mch.weixin.qq.com/v3/payscore/serviceorder', {
                service_id: conf.serviceId,
                appid: conf.appid,
                out_order_no: out_order_no,
                openid : openid,
                need_user_confirm : false,
                service_introduction : service_introduction,
                notify_url: url.resolve(conf.notifyUrl, notify_url),
                time_range : {
                    start_time : startTime
                },
                risk_fund : {
                    name : 'ESTIMATE_ORDER_COST',
                    amount : amount * 1000
                }
            })

            console.log(res)

            return res.statusText == 'OK' ? res.data : null

        } catch (error) {
            console.log(error.message)
        }

        return null

    }

    //免密支付取消订单
    async payscoreServiceorderCancel(out_order_no:string, reason:string) {
        try {
            const conf:any = this.config()
            if(!conf) return null
            const res = await this.http.axiosRef.post(`https://api.mch.weixin.qq.com/v3/payscore/serviceorder/${out_order_no}/cancel`, {
                service_id: conf.serviceId,
                appid: conf.appid,
                reason : reason
            })

            console.log(res)

            return res.statusText == 'OK' ? res.data : null

        } catch (error) {
            console.log(error.message)
        }

        return null

    }

    


    //小程序下单
    async pay(amount:number, orderNo:string, openid:string, description:string, notify_url:string) {
        const conf:any = this.config()

        const pay = new WxPay({
            appid: conf.appid,
            mchid: conf.mchid,
            publicKey: Buffer.from(conf.publicKey, 'utf-8'), // 公钥
            privateKey: Buffer.from(conf.privateKey, 'utf-8'), // 秘钥
        });

        let baseNotifyUrl = conf.notifyUrl
        if(baseNotifyUrl.endsWith('/') == false) {
            baseNotifyUrl += '/'
        }

        const result = await pay.transactions_jsapi({
            description: description,
            out_trade_no: orderNo,
            notify_url: url.resolve(baseNotifyUrl, notify_url),
            amount: {
              total: amount * 100,
            },
            payer: {
              openid: openid,
            }
        })


        if(result.status != 200) return null
        return {
            appId: result.appId,
            timeStamp: result.timeStamp,
            nonceStr: result.nonceStr,
            package: result.package,
            signType: result.signType,
            paySign: result.paySign,
          }
    }

    //获取手机号码
    async getuserphonenumber(code:string) {
        const ACCESS_TOKEN = await this.cache.get(this.configure.get('configure'))//this.common.wxAccessToken
        try {
            if(!ACCESS_TOKEN) return null
            const res = await this.http.axiosRef.post('https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=' + ACCESS_TOKEN, {
                code
            })

            console.log(res.data.phone_info.watermark)

            if(res.statusText == 'OK' && res.data) {
                if(res.data.errcode == 0) {
                    return res.data.phone_info.phoneNumber
                }
            }


        } catch (error) {
            console.log(error.message)
        }
        
        return null
    }
}
